import socket
from txosc import osc
from Bases import BaseObject
from Bases import OSCBaseObject
from comm.osc.osc_sender import UnicastOSCSender

import widgets

class mrmrController(OSCBaseObject):
    osc_address = 'mrmr'
    def __init__(self, **kwargs):
        self.MainController = kwargs.get('MainController')
        self.comm = self.MainController.comm
        kwargs.setdefault('osc_parent_node', self.MainController.comm.osc_io.root_node)
        super(mrmrController, self).__init__(**kwargs)
        self.IBserver = mrmrServer(mrmrController=self)
        self.WidgetManager = WidgetManager(mrmrController=self, hostaddr='192.168.168.90')
        self.build_test_widgets()
        self.osc_io = self.MainController.comm.osc_io
        self.comm.connect('state_changed', self.on_comm_state)
        
        
    def build_test_widgets(self):
        for y in range(1, 3):
            for x in range(1, 3):
                self.WidgetManager.add_widget('Button', grid_pos=[x, y], label='%s,%s' % (x, y))
        self.WidgetManager.add_widget('Toggle', grid_pos=[1, 3], label='Toggle')
        self.WidgetManager.add_widget('xyPad', grid_pos=[3, 1], span=[2, 2])
        self.testslider = self.WidgetManager.add_widget('Slider', grid_pos=[1, 4], span=[4, 1])
        self.WidgetManager.widgets[0].connect('press', self.on_test_btn_press)
        self.WidgetManager.widgets[0].connect('release', self.on_test_btn_release)
    def on_test_btn_press(self, **kwargs):
        self.testslider.value = .5
    def on_test_btn_release(self, **kwargs):
        self.testslider.value = 0.
        
    def add_osc_preprocess(self, **kwargs):
        if self.osc_io.connected:
            self.osc_io._receiver.add_preprocess(self.osc_recv_preprocess)
            self.osc_io._sender.add_preprocess(self.osc_send_preprocess)
            
    def osc_recv_preprocess(self, data):
        if '/mrmr/' in data:
            if data[0] == '/':
                msg, leftover = osc.Message.fromBinary(data)
                
                l = msg.address.split('/')[2:]
                l.reverse()
                l.insert(1, 'mrmr')
                new_address = '/%s' % ('/'.join(l))
                msg.address = new_address
                new_data = msg.toBinary()
                print 'recv preprocess:'
                print ' data=' + data
                print '\n newaddress=' + new_address
                return new_data
        return data
        
    def osc_send_preprocess(self, msg):
        address = msg.address
        if '/mrmr/' in address:
            if address[0] == '/':
                print 'send preprocess:'
                print 'oldaddress=' + address
                #msg, leftover = osc.Message.fromBinary(data)
                l = address.split('/')
                root = 'DWT-iPad'
                l = l[3:]
                l.reverse()
                l.insert(0, 'mrmr')
                #l.append(root)
                new_address = '/%s' % ('/'.join(l))
                msg.address = new_address
                #new_data = msg.toBinary()
                print 'newaddress=' + new_address
                #return new_data
        #return data
        
    def on_comm_state(self, **kwargs):
        if kwargs.get('state'):
            self.add_osc_preprocess()
            #self.WidgetManager.init_client()
            self.testslider.value = .5
        
class mrmrServer(OSCBaseObject):
    def __init__(self, **kwargs):
        super(mrmrServer, self).__init__(**kwargs)
        self.mrmrController = kwargs.get('mrmrController')
        self.MainController = self.mrmrController.MainController
        self.MainController.comm.connect('state_changed', self.on_comm_state)
        
    def on_comm_state(self, **kwargs):
        if kwargs.get('state'):
            self.test_stuff()
    def test_stuff(self):
        return
        d = {1:{}, 2:{}}
        i = 0
        for y in range(1, 3):
            for x in range(1, 3):
                d[1][i] = {'cls':'Button', 
                           'attrs':{'id':i, 'grid_pos':[x, y], 'label':i+1}}
                i += 1
        d[2][i] = {'cls':'Slider', 'attrs':{'grid_pos':[1, 4], 'span':[4, 1], 'id':i, 'label':i+1}}
        d[2][i+1] = {'cls':'xyPad', 'attrs':{'grid_pos':[3, 1], 'span':[2, 2], 'id':i+1, 'label':i+2}}
        d[2][i+2] = {'cls':'Toggle', 'attrs':{'grid_pos':[1, 3], 'span':[1, 1], 'id':i+2, 'label':'Toggle'}}
        self.widget_mgr = WidgetManager(mrmrController=self.mrmrController, 
                                        hostaddr='192.168.1.103', widget_info=d)
        #self.widget_mgr.init_client()
        
class WidgetManager(BaseObject):
    def __init__(self, **kwargs):
        self.connected = False
        super(WidgetManager, self).__init__(**kwargs)
        self.mrmrController = kwargs.get('mrmrController')
        self.hostaddr = kwargs.get('hostaddr')
        self.hostport = kwargs.get('hostport', 31337)
        self.widget_info = kwargs.get('widget_info', {})
        self.widgets = {}
        self.widgets_by_bank = {}
        #self.widget_osc_nodes = {}
        #self._build_widgets()
        self.socket = None
        
    def add_widget(self, cls_name, **kwargs):
        cls = widgets.widget_classes.get(cls_name)
        if cls:
            new_kwargs = kwargs.copy()
            new_kwargs.update({'id':self.next_widget_index, 
                               'osc_parent_node':self.mrmrController.osc_node})
            new_kwargs.setdefault('bank_number', 1)
            w = cls(**new_kwargs)
            self.widgets.update({w.id:w})
            if w.bank_number not in self.widgets_by_bank:
                self.widgets_by_bank.update({w.bank_number:{}})
            self.widgets_by_bank[w.bank_number].update({w.id:w})
        return w
            
    @property
    def next_widget_index(self):
        return len(self.widgets)
        
#    def _build_widgets(self):
#        for pkey, pval in self.widget_info.iteritems():
#            self.widgets.update({pkey:{}})
#            for wkey, wval in pval.iteritems():
#                cls = widgets.widget_classes.get(wval['cls'])
##                if cls.widget_name not in self.widget_osc_nodes:
##                    node = self.mrmrController.osc_node.add_new_node(name=cls.widget_name)
##                    self.widget_osc_nodes.update({cls.widget_name:node})
#                w_kwargs = wval['attrs'].copy()
#                #w_kwargs.update({'osc_parent_node':self.widget_osc_nodes[cls.widget_name]})
#                w_kwargs.update({'osc_parent_node':self.mrmrController.osc_node})
#                w = cls(**w_kwargs)
#                self.widgets[pkey].update({w.id:w})
        
    def do_connect(self):
        if not self.connected:
            self.socket = socket.socket()
            try:
                self.socket.connect((self.hostaddr, self.hostport))
                self.connected = True
                print 'mrmr server connect', self.hostaddr
            except socket.error, msg:
                self.socket.close()
                self.socket = None
                print 'mrmr server error:', msg
    
    def do_disconnect(self):
        if self.socket:
            self.socket.close()
            self.socket = None
        self.connected = False
    
    def init_client(self):
        self.do_connect()
        self.send('/mrmrIB mrmr_clear_all\n')
        
        msg = '|+|\n'
        for bkey, bval in self.widgets_by_bank.iteritems():
            #self.send('/mrmrIB mrmr_changeBank:%s\n' % (bank))
            l = [w.build_string() for w in bval.values()]
            msg += '\n'.join(l) + '\n'
            if bkey < len(self.widgets_by_bank)-1:
                msg += '|*|\n'
        msg += '|-|\n'
        self.send(msg)
        self.do_disconnect()
        
    def send(self, data):
        print 'mrmrserver send: ', data
        if self.connected:
            self.socket.send(data)